--[[
	Auctioneer Advanced
	Version: 5.6.4377 (KangaII)
	Revision: $Id: CoreAPI.lua 4279 2009-05-28 21:50:10Z Nechckn $
	URL: http://auctioneeraddon.com/

	This is an addon for World of Warcraft that adds statistical history to the auction data that is collected
	when the auction is scanned, so that you can easily determine what price
	you will be able to sell an item for at auction or at a vendor whenever you
	mouse-over an item in the game

	License:
		This program is free software; you can redistribute it and/or
		modify it under the terms of the GNU General Public License
		as published by the Free Software Foundation; either version 2
		of the License, or (at your option) any later version.

		This program is distributed in the hope that it will be useful,
		but WITHOUT ANY WARRANTY; without even the implied warranty of
		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
		GNU General Public License for more details.

		You should have received a copy of the GNU General Public License
		along with this program(see GPL.txt); if not, write to the Free Software
		Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

	Note:
		This AddOn's source code is specifically designed to work with
		World of Warcraft's interpreted AddOn system.
		You have an implicit license to use this AddOn with these facilities
		since that is its designated purpose as per:
		http://www.fsf.org/licensing/licenses/gpl-faq.html#InterpreterIncompat
]]
local L = LibStub("AceLocale-3.0"):GetLocale("Auc_CoreLocale")
if not AucAdvanced then return end

AucAdvanced.API = {}
local lib = AucAdvanced.API
local private = {}

lib.Print = AucAdvanced.Print
local Const = AucAdvanced.Const

--local replicate, empty, fill = AucAdvanced.Replicate, AucAdvanced.Empty, AucAdvanced.Fill
local empty = wipe

local tinsert = table.insert
local tremove = table.remove
local next = next
local pairs = pairs
local ipairs = ipairs
local ceil = math.ceil
local max = math.max
local tostring = tostring
local type = type

--[[
	The following functions are defined for modules's exposed methods:

	GetName()         (ALL*)  Should return this module's full name
	OnLoad()          (ALL*)  Receives load message for all modules
	Processor()       (ALL)   Processes messages sent by Auctioneer
	CommandHandler()  (ALL)   Slash command handler for this module
	ScanProcessor {}  (ALL)   Processes items from the scan manager
	GetPrice()        (STAT*) Returns estimated price for item link
	GetPriceColumns() (STAT)  Returns the column names for GetPrice
	StartScan()       (SCAN*) Begins an AH scan session
	IsScanning()      (SCAN*) Indicates an AH scan is in session
	AbortScan()       (SCAN)  Cancels the currently running scan
	Hook { }          (ALL)   Functions that are hooked by the module
    GetItemPDF()      (STAT*) Provides a probability distribution function for an item price


	Module type in parentheses to describe which ones provide.
	Possible Module Types are STAT, UTIL, SCAN.  ALL is a shorthand for all three.
	A * after the module type states the function is REQUIRED.

	Please visit http://norganna.org/wiki/Auctioneer/5.0/Modules_API for a
	more complete specification.
]]

-- this is actually called from a dummy module in CoreUtil
function lib.Processor(event, ...)
	if event == "scanstats" then
		private.clearCaches(...)
	end
end

do
    local EPSILON = 0.000001;
    local IMPROVEMENT_FACTOR = 0.8;
    local CORRECTION_FACTOR = 1000; -- 10 silver per gold, integration steps at tail
    local FALLBACK_ERROR = 1;       -- 1 silver per gold fallback error max
    local cache = {};
    local pdfList = {};
    local engines = {};
    local abs = math.abs;
    local floor = math.floor;
    local ERROR = 0.05;
    local GetSetting = AucAdvanced.Settings.GetSetting;
    local GetItemInfo = GetItemInfo;
    local GetCVar = GetCVar;
    local assert = assert;
    -- local LOWER_INT_LIMIT, HIGHER_INT_LIMIT = -100000, 10000000;
    --[[
        This function acquires the current market value of the mentioned item using
        a configurable algorithm to process the data used by the other installed
        algorithms.

        The returned value is the most probable value that the item is worth
        using the algorithms in each of the STAT modules as specified
        by the GetItemPDF() function.

        AucAdvanced.API.GetMarketValue(itemLink, serverKey)
    ]]
    function lib.GetMarketValue(itemLink, serverKey)
        ERROR = GetSetting("marketvalue.accuracy");
        local _;
        if type(itemLink) == 'number' then _, itemLink = GetItemInfo(itemLink) end
        if not itemLink then return; end
        local saneLink = AucAdvanced.SanitizeLink(itemLink)

        -- Look up in the cache if it's recent enough
        local cacheTable = cache[lib.GetSigFromLink(itemLink)..":"..(serverKey or GetCVar("realmName"))];
        if cacheTable then
            return cacheTable.value, cacheTable.seen, cacheTable.stats;
        end

        if nLog then nLog.AddMessage("Auctioneer", "Market Pricing", N_NOTICE, "Cache Miss", "Auctioneer Advanced missed market pricing cache on item '"..itemLink.."'"); end


        local upperLimit, lowerLimit, seen = 0, 1e11, 0;

        if #engines == 0 then
            -- Rebuild the engine cache
            local modules = AucAdvanced.GetAllModules(nil, "Stat")
            for pos, engineLib in ipairs(modules) do
                local fn = engineLib.GetItemPDF;
                if fn then
                    tinsert(engines, {pdf = fn, array = engineLib.GetPriceArray});
                elseif nLog then
                    nLog.AddMessage("Auctioneer", "Market Pricing", N_WARNING, "Missing PDF", "Auctioneer Advanced engine '"..engineLib.GetName().."' does not have a GetItemPDF() function. This check will be removed in the near future in favor of faster calls. Implement this function.");
                end
            end
        end

        -- print("Calculating", itemLink);

        -- Run through all of the stat modules and get the PDFs
        local c, oldPdfMax, total = 0, #pdfList, 0;
        local convergedFallback = nil;
        for _, engine in ipairs(engines) do
            local i, min, max, area = engine.pdf(saneLink, serverKey);

            if type(i) == 'number' then
                -- This is a fallback
                if convergedFallback == nil or (type(convergedFallback) == 'number' and math.abs(convergedFallback - i) < FALLBACK_ERROR * convergedFallback / 10000) then
                    convergedFallback = i;
                else
                    convergedFallback = false;      -- Cannot converge on fallback pricing
                end
            end

            local priceArray = engine.array(saneLink, serverKey);

            if priceArray and (priceArray.seen or 0) > seen then
                seen = priceArray.seen;
            end

            if i and type(i) ~= 'number' then   -- pdfList[++c] = i;
                total = total + (area or 1);                                -- Add total area, assume 1 if not supplied
                c = c + 1;
                pdfList[c] =  i;
                if min < lowerLimit then lowerLimit = min; end
                if max > upperLimit then upperLimit = max; end
            end
        end

        -- Clean out extras if needed
        for i = c+1, oldPdfMax do
            pdfList[i] = nil;
        end

        if #pdfList == 0 and convergedFallback then
            if nLog then nLog.AddMessage("Auctioneer", "Market Pricing", N_WARNING, "Fallback Pricing Used", "Fallback pricing used due to no available PDFs on item "..itemlink); end
            return convergedFallback, 1, 1;
        end


        assert(lowerLimit > -1/0 and upperLimit < 1/0, "Invalid bounds detected while pricing "..(GetItemInfo(itemLink) or itemLink)..": "..tostring(lowerLimit).." to "..tostring(upperLimit));



        -- Determine the totals from the PDFs
        local delta = (upperLimit - lowerLimit) * .01;

        if #pdfList == 0 or delta < EPSILON or total < EPSILON then
            return;                 -- No PDFs available for this item
        end

        local limit = total/2;
        local midpoint, lastMidpoint = 0, 0;

        -- Now find the 50% point
        repeat
            lastMidpoint = midpoint;
            total = 0;

            assert(delta > 0, "Infinite loop detected during market pricing for "..(GetItemInfo(itemLink) or itemLink));

            for x = lowerLimit, upperLimit, delta do
                for i = 1, #pdfList do
                    local val = pdfList[i](x);
                    total = total + val * delta;
                end

                if total > limit then
                    midpoint = x;
                    break;
                end
            end

            delta = delta * IMPROVEMENT_FACTOR;


            if midpoint ~= midpoint or midpoint == 0 then
                if nLog and midpoint ~= midpoint then
                    nLog.AddMessage("Auctioneer", "Market Pricing", N_WARNING, "Unable To Calculate", "A NaN value was detected while processing the midpoint for PDF of "..(GetItemInfo(itemLink) or itemLink).."... Giving up.");
                elseif nLog then
                    nLog.AddMessage("Auctioneer", "Market Pricing", N_NOTICE, "Unable To Calculate", "A zero total was detected while processing the midpoint for PDF of "..(GetItemInfo(itemLink) or itemLink).."... Giving up.");
                end

                if convergedFallback then
                    if nLog then
                        nLog.AddMessage("Auctioneer", "Market Pricing", N_WARNING, "Fallback Pricing Used", "Fallback pricing used due to NaN/Zero total for item "..itemLink);
                    end
                    return convergedFallback, 1, 1;
                end
                return;                 -- Cannot calculate: NaN
            end

        until abs(midpoint - lastMidpoint)/midpoint < ERROR;

        if midpoint and midpoint > 0 then
            midpoint = floor(midpoint + 0.5);   -- Round to nearest copper

            -- Cache before finishing up
            local cacheTable = {}
            cache[lib.GetSigFromLink(itemLink)..":"..(serverKey or GetCVar("realmName"))] = cacheTable;
            cacheTable.time = GetTime();
            cacheTable.value = midpoint;
            cacheTable.seen = seen;
            cacheTable.stats = #pdfList;


            return midpoint, seen, #pdfList;
        else
            if nLog then
                nLog.AddMessage("Auctioneer", "Market Pricing", N_WARNING, "Unable To Calculate", "No midpoint was detected for item "..(GetItemInfo(itemLink) or itemLink).."... Giving up.");
            end
            return;
        end

    end

    -- Now hook NewModule so that we clear the engine cache when a new module comes into play
    local oldNewModule = AucAdvanced.NewModule;
    AucAdvanced.NewModule = function(...)
        engines = {};               -- Clear the engine list
        return oldNewModule(...);   -- Tailcall original function
    end

    -- Clears the cache for AucAdvanced.API.GetMarketValue()
    function lib.ClearMarketCache()
        for x, _ in pairs(cache) do
            cache[x] = nil;
        end
    end
end

function lib.ClearItem(itemLink, serverKey)
	local saneLink = AucAdvanced.SanitizeLink(itemLink)
	local modules = AucAdvanced.GetAllModules("ClearItem")
	for pos, engineLib in ipairs(modules) do
		engineLib.ClearItem(saneLink, serverKey)
	end
	lib.ClearMarketCache()
end

function lib.GetAlgorithms(itemLink)
	local saneLink = AucAdvanced.SanitizeLink(itemLink)
	local engines = {}
	local modules = AucAdvanced.GetAllModules()
	for pos, engineLib in ipairs(modules) do
		if engineLib.GetPrice or engineLib.GetPriceArray then
			if not engineLib.IsValidAlgorithm
			or engineLib.IsValidAlgorithm(saneLink) then
				local engine = engineLib.GetName()
				tinsert(engines, engine)
			end
		end
	end
	return engines
end

function lib.IsValidAlgorithm(algorithm, itemLink)
	local saneLink = AucAdvanced.SanitizeLink(itemLink)
	local modules = AucAdvanced.GetAllModules()
	for pos, engineLib in ipairs(modules) do
		if engineLib.GetName() == algorithm and (engineLib.GetPrice or engineLib.GetPriceArray) then
			if engineLib.IsValidAlgorithm then
				return engineLib.IsValidAlgorithm(saneLink)
			end
			return true
		end
	end
	return false
end

private.algorithmstack = {}
function lib.GetAlgorithmValue(algorithm, itemLink, serverKey, reserved)
	if (not algorithm) then
        if nLog then nLog.AddMessage("Auctioneer", "API", N_ERROR, "Incorrect Usage", "No pricing algorithm supplied to GetAlgorithmValue") end
		return
	end
	if type(itemLink) == "number" then
		local _
		_, itemLink = GetItemInfo(itemLink)
	end
	if (not itemLink) then
		if nLog then nLog.AddMessage("Auctioneer", "API", N_ERROR, "Incorrect Usage", "No itemLink supplied to GetAlgorithmValue") end
		return
	end

    if reserved then
        lib.ShowDeprecationAlert("AucAdvanced.API.GetAlgorithmValue(algorithm, itemLink, serverKey)",
            "The 'faction' and 'realm' parameters are deprecated in favor of the new 'serverKey' parameter. Use this instead."
        );

        serverKey = reserved.."-"..serverKey;
    end
    serverKey = serverKey or AucAdvanced.GetFaction()

	local saneLink = AucAdvanced.SanitizeLink(itemLink)
	local modules = AucAdvanced.GetAllModules()
	for pos, engineLib in ipairs(modules) do
		if engineLib.GetName() == algorithm and (engineLib.GetPrice or engineLib.GetPriceArray) then
			if engineLib.IsValidAlgorithm
			and not engineLib.IsValidAlgorithm(saneLink) then
				return
			end
			local algosig = strjoin(":", algorithm, saneLink, serverKey)
			for pos, history in ipairs(private.algorithmstack) do
				if (history == algosig) then
					-- We are looping
					local origAlgo = private.algorithmstack[1]
					local endSize = #(private.algorithmstack)+1
					while (#(private.algorithmstack)) do
						tremove(private.algorithmstack)
					end
					error(("Cannot solve price algorithm for: %s. (Recursion at level %d->%d: %s)"):format(origAlgo, algosig, endSize, pos))
				end
			end

			local price, seen, array
			tinsert(private.algorithmstack, algosig)
			if (engineLib.GetPriceArray) then
				array = engineLib.GetPriceArray(saneLink, serverKey)
				if (array) then
					price = array.price
					seen = array.seen
				end
			else
				price = engineLib.GetPrice(saneLink, serverKey)
			end
			tremove(private.algorithmstack, -1)
			return price, seen, array
		end
	end
	--error(("Cannot find pricing algorithm: %s"):format(algorithm))
	return
end

private.scandataIndex = {}
-- ensure home and neutral factions for current realm are always present
-- unlike the tables for other serverKeys, these tables are *not* weak
private.scandataIndex[GetRealmName().."-"..UnitFactionGroup("player")] = {}
private.scandataIndex[GetRealmName().."-Neutral"] = {}
local weaktablemeta = {__mode="kv"}
function private.GetSubImageById(itemId, faction, realm)
	faction = faction or AucAdvanced.GetFactionGroup()
	realm = realm or GetRealmName()
	local serverKey = realm.."-"..faction

	local indexResults = private.scandataIndex[serverKey]
	if not indexResults then
		indexResults = setmetatable({}, weaktablemeta) -- use weak tables for other serverKeys
		private.scandataIndex[serverKey] = indexResults
	end

	local itemResults = indexResults[itemId]
	if not itemResults then
		itemResults = {}
		local scandata = AucAdvanced.Scan.GetScanData(faction, realm)
		for pos, data in ipairs(scandata.image) do
			if data[Const.ITEMID] == itemId then
				tinsert(itemResults, data)
			end
		end
		indexResults[itemId] = itemResults
	end

	return itemResults
end

private.prevQuery = { empty = true }
private.curResults = {}
function lib.QueryImage(query, faction, realm, ...)
	local prevQuery = private.prevQuery
	local curResults = private.curResults

	-- is this the same query as last time?
	local samequery = true
	for k,v in pairs(prevQuery) do
		if k ~= "page" and v ~= query[k] then
			samequery = false
			break
		end
	end
	if samequery then
		for k,v in pairs(query) do
			if k ~= "page" and v ~= prevQuery[k] then
				samequery = false
				break
			end
		end
		if samequery then
			return curResults
		end
	end

	-- reset results and save a copy of query
	empty(curResults)
	empty(prevQuery)
	for k, v in pairs(query) do prevQuery[k] = v end

	-- get image to search - may be the whole snapshot or a subset
	local image
	if query.itemId then
		image = private.GetSubImageById(query.itemId, faction, realm)
	else
		local scandata = AucAdvanced.Scan.GetScanData(faction, realm)
		image = scandata.image
	end

	local saneQueryLink
	if query.link then
		saneQueryLink = AucAdvanced.SanitizeLink(query.link)
	end

	-- scan image to build a table of auctions that match query
	local ptr, finish = 1, #image
	while ptr <= finish do
		repeat
			local data = image[ptr]
			ptr = ptr + 1
			if not data then break end
			if bit.band(data[Const.FLAG] or 0, Const.FLAG_UNSEEN) == Const.FLAG_UNSEEN then break end
			if query.filter and query.filter(data, ...) then break end
			if saneQueryLink and data[Const.LINK] ~= saneQueryLink then break end
			if query.suffix and data[Const.SUFFIX] ~= query.suffix then break end
			if query.factor and data[Const.FACTOR] ~= query.factor then break end
			if query.minUseLevel and data[Const.ULEVEL] < query.minUseLevel then break end
			if query.maxUseLevel and data[Const.ULEVEL] > query.maxUseLevel then break end
			if query.minItemLevel and data[Const.ILEVEL] < query.minItemLevel then break end
			if query.maxItemLevel and data[Const.ILEVEL] > query.maxItemLevel then break end
			if query.class and data[Const.ITYPE] ~= query.class then break end
			if query.subclass and data[Const.ISUB] ~= query.subclass then break end
			if query.quality and data[Const.QUALITY] ~= query.quality then break end
			if query.invType and data[Const.IEQUIP] ~= query.invType then break end
			if query.seller and data[Const.SELLER] ~= query.seller then break end
			if query.name then
				local name = data[Const.NAME]
				if not (name and name:lower():find(query.name:lower(), 1, true)) then break end
			end

			local stack = data[Const.COUNT]
			local nextBid = data[Const.PRICE]
			local buyout = data[Const.BUYOUT]
			
			--试着屏蔽千位党
			if buyout > 100000000 and nextBid <= 1000000 then break end
			if buyout > 100000000 and nextBid > 100000000 then break end
			--if nextBid < buyout/10 then break end
			--从查询结果剔除黑名单的人
			if AucAdvanced.Modules.Filter.Basic and AucAdvanced.Modules.Filter.Basic.IgnoreList and AucAdvanced.Modules.Filter.Basic.IgnoreList[data[Const.SELLER]] then break end
			--if AucAdvanced.Modules.Filter.Basic.IgnoreList[data[Const.SELLER]] then break end
			--
			if query.perItem and stack > 1 then
				nextBid = ceil(nextBid / stack)
				buyout = ceil(buyout / stack)
			end
			if query.minStack and stack < query.minStack then break end
			if query.maxStack and stack > query.maxStack then break end
			if query.minBid and nextBid < query.minBid then break end
			if query.maxBid and nextBid > query.maxBid then break end
			

			if query.minBuyout and buyout < query.minBuyout then break end
			if query.maxBuyout and buyout > query.maxBuyout then break end

			-- If we're still here, then we've got a winner
			tinsert(curResults, data)
		until true
	end

	return curResults
end

function private.clearCaches(scanstats)
	local serverKey = AucAdvanced.GetFaction()
	empty(private.scandataIndex[serverKey])

	empty(private.curResults)
	empty(private.prevQuery)
	private.prevQuery.empty = true
end

function lib.UnpackImageItem(item)
	return AucAdvanced.Scan.UnpackImageItem(item)
end

function lib.ListUpdate()
	if lib.IsBlocked() then return end
	AucAdvanced.SendProcessorMessage("listupdate")
end

function lib.BlockUpdate(block, propagate)
	local blocked
	if block == true then
		blocked = true
		private.isBlocked = true
		AuctionFrameBrowse:UnregisterEvent("AUCTION_ITEM_LIST_UPDATE")
	else
		blocked = false
		private.isBlocked = nil
		AuctionFrameBrowse:RegisterEvent("AUCTION_ITEM_LIST_UPDATE")
	end

	if (propagate) then
		AucAdvanced.SendProcessorMessage("blockupdate", blocked)
	end
end

function lib.IsBlocked()
	return private.isBlocked == true
end

--Market matcher APIs
private.matcherlist = AucAdvanced.Settings.GetSetting("matcherlist")
function lib.GetBestMatch(itemLink, algorithm, serverKey, reserved)
	local saneLink = AucAdvanced.SanitizeLink(itemLink)

    if reserved then
        lib.ShowDeprecationAlert("AucAdvanced.API.GetBestMatch(itemLink, algorithm, serverKey)",
            "The 'realm' and 'faction' parameters have been removed in favor of a single "..
            "variable 'serverKey' which should be used in the future."
        );

        serverKey = reserved.."-"..serverKey;
    end

	-- TODO: Make a configurable algorithm.
	-- This algorithm is currently less than adequate.

    local faction = (serverKey or ""):match("^[^%-]+%-(.+)$") or AucAdvanced.GetFaction()
	local realm = (serverKey or ""):match("^([^%-]+)%-.+$") or GetRealmName()

	local matchers = lib.GetMatchers(saneLink)
	local total, count, diff, _ = 0, 0, 0


	local priceArray = {}

	if algorithm == "market" then
		priceArray.price, priceArray.seen = lib.GetMarketValue(saneLink, serverKey)
	elseif type(algorithm) == "string" then
		_, _, priceArray = lib.GetAlgorithmValue(algorithm, saneLink, serverKey)
	else
		priceArray.price = algorithm
	end

	local InfoString = ""
	if not priceArray or not priceArray.price then return end
	for index, matcher in ipairs(matchers) do
		if lib.IsValidMatcher(matcher, saneLink) then
			local value, MatchpriceArray = lib.GetMatcherValue(matcher, saneLink, priceArray.price)
			priceArray.price = value
			count = count + 1
			diff = diff + MatchpriceArray.diff
			if MatchpriceArray.returnstring then
				InfoString = strjoin("\n", InfoString, MatchpriceArray.returnstring)
			end
		end
	end

	if (priceArray.price > 0) then
		return priceArray.price, total, count, diff/count, InfoString
	end
end

function lib.GetMatcherDropdownList()
	private.matcherlist = AucAdvanced.Settings.GetSetting("matcherlist")
	if not private.matcherlist or #private.matcherlist == 0 then
		lib.GetMatchers()
	end
	if not private.matcherlist or #private.matcherlist == 0 then
		return
	end
	local dropdownlist = {}
	for index, value in ipairs(private.matcherlist) do
		dropdownlist[index] = tostring(index)..": "..tostring(private.matcherlist[index])
	end
	return dropdownlist
end

function lib.GetMatchers(itemLink)
	local saneLink = AucAdvanced.SanitizeLink(itemLink)
	private.matcherlist = AucAdvanced.Settings.GetSetting("matcherlist")
	local engines = {}
	local modules = AucAdvanced.GetAllModules()
	for pos, engineLib in ipairs(modules) do
		if engineLib.GetMatchArray then
			if not engineLib.IsValidMatcher
			or engineLib.IsValidMatcher(saneLink) then
				local engine = engineLib.GetName()
				tinsert(engines, engine)
			end
		end
	end
	local insetting = false
	local stillactive = false
	--check to see if there are any new matchers.  If so, add them to the end of the running order.
	--There is no check to see if matchers are missing, as this would destroy the saved order.  Instead, invalid matchers can be called without errors.
	if private.matcherlist then
		for index, matcher in ipairs(engines) do
			for i, j in ipairs(private.matcherlist) do
				if matcher == j then insetting = true
				end
			end
			if not insetting then
				AucAdvanced.Print(L["AucAdvanced: New matcher found: "]..tostring(matcher))
				tinsert(private.matcherlist, matcher)
			end
			insetting = false
		end
	else
		private.matcherlist = engines
	end
	AucAdvanced.Settings.SetSetting("matcherlist", private.matcherlist)
	return private.matcherlist
end

function lib.IsValidMatcher(matcher, itemLink)
	local saneLink = AucAdvanced.SanitizeLink(itemLink)
	local engines = {}
	local modules = AucAdvanced.GetAllModules()
	for pos, engineLib in ipairs(modules) do
		local engine = engineLib.GetName()
		if engine == matcher and engineLib.GetMatchArray then
			if engineLib.IsValidMatcher then
				return engineLib.IsValidMatcher(saneLink)
			end
			return engineLib
		end
	end
	return false
end

function lib.GetMatcherValue(matcher, itemLink, price)
	local saneLink = AucAdvanced.SanitizeLink(itemLink)
	if (type(matcher) == "string") then
		matcher = lib.IsValidMatcher(matcher, saneLink)
	end
	if not matcher then return end
	--If matcher is not a table at this point, the following code will throw an "attempt to index a <something> value" type error
	local matchArray = matcher.GetMatchArray(saneLink, price)
	if not matchArray then
		matchArray = {}
		matchArray.value = price
		matchArray.diff = 0
	end

	return matchArray.value, matchArray
end


-- Allows the return of Appraiser price values to other functions.
-- If Appraiser is not loaded it uses Market Price
function lib.GetAppraiserValue(itemLink, useMatching)
	local saneLink = AucAdvanced.SanitizeLink(itemLink)
	local newBuy, newBid, _, seen, curModelText, MatchString, stack, number, duration
	if not AucAdvanced.Modules.Util.Appraiser then
		newBuy, seen = AucAdvanced.API.GetMarketValue(saneLink)
		curModelText = "Market"
		return newBuy, newBuy, seen, curModelText
	end

	newBuy, newBid, _, seen, curModelText, MatchString, stack, number, duration = AucAdvanced.Modules.Util.Appraiser.GetPrice(saneLink, 0, useMatching)
	lib.ShowDeprecationAlert("AucAdvanced.Modules.Util.Appraiser.GetPrice(itemLink, _, useMatching)");

	return newBid, newBuy, seen, curModelText, MatchString, stack, number, duration
end

-- Signature conversion functions

-- Creates an AucAdvanced signature from an item link
function lib.GetSigFromLink(link)
	local sig
	local itype, id, suffix, factor, enchant, seed = AucAdvanced.DecodeLink(link)
	if itype == "item" then
		if enchant ~= 0 then
			sig = ("%d:%d:%d:%d"):format(id, suffix, factor, enchant)
		elseif factor ~= 0 then
			sig = ("%d:%d:%d"):format(id, suffix, factor)
		elseif suffix ~= 0 then
			sig = ("%d:%d"):format(id, suffix)
		else
			sig = tostring(id)
		end
	else
		lib.Print(L["Link is not item"])
	end
	return sig
end

-- Creates an item link from an AucAdvanced signature
function lib.GetLinkFromSig(sig)
	local link, name
	local id, suffix, factor, enchant = strsplit(":", sig)
	if not suffix then suffix = "0" end
	if not factor then factor = "0" end
	if not enchant then enchant = "0" end

	link = ("item:%d:%d:0:0:0:0:%d:%d:0"):format(id, enchant, suffix, factor)
	name, link = GetItemInfo(link)
	link = AucAdvanced.SanitizeLink(link)
	return link, name -- name is ignored by most calls
end


-------------------------------------------------------------------------------
-- Statistical devices created by Matthew 'Shirik' Del Buono
-- For Auctioneer Advanced
-------------------------------------------------------------------------------
local sqrtpi = math.sqrt(math.pi);
local sqrtpiinv = 1/sqrtpi;
local sq2pi = math.sqrt(2*math.pi);
local pi = math.pi;
local exp = math.exp;
local bellCurveMeta = {
    __index = {
        SetParameters = function(self, mean, stddev)
            if (stddev == 0) then
                error("Standard deviation cannot be zero");
            elseif (stddev ~= stddev) then
                error("Standard deviation must be a real number");
            end
			if stddev < .1 then --need to prevent obsurdly small stddevs like 1e-11, as they cause freeze-ups
				stddev = .1
			end
            self.mean = mean;
            self.stddev = stddev;
            self.param1 = 1/(stddev*sq2pi);     -- Make __call a little faster where we can
            self.param2 = 2*stddev^2;
        end
    },
    -- Simple bell curve call
    __call = function(self, x)
        local n = self.param1*exp(-(x-self.mean)^2/self.param2);
        -- if n ~= n then
            -- DEFAULT_CHAT_FRAME:AddMessage("-----------------");
            -- DevTools_Dump{param1 = self.param1, param2 = self.param2, x = x, mean = self.mean, stddev = self.stddev, exp = exp(-(x-self.mean)^2/self.param2)};
            -- error(x.." produced NAN ("..tostring(n)..")");
        -- end
        return n;
    end
}
-------------------------------------------------------------------------------
-- Creates a bell curve object that can then be manipulated to pass
-- as a PDF function. This is a recyclable object -- the mean and
-- standard deviation can be updated as necessary so that it does not have
-- to be regenerated
--
-- Note: This creates a bell curve with a standard deviation of 1 and
-- mean of 0. You will probably want to update it to your own desired
-- values by calling return:SetParameters(mean, stddev)
-------------------------------------------------------------------------------
function lib.GenerateBellCurve()
    return setmetatable({mean=0, stddev=1, param1=sqrtpiinv, param2=2}, bellCurveMeta);
end

-- Dumps out market pricing information for debugging. Only handles bell curves for now.
function lib.DumpMarketPrice(itemLink, serverKey)
	local modules = AucAdvanced.GetAllModules(nil, "Stat");
	for pos, engineLib in ipairs(modules) do
		local success, result = pcall(engineLib.GetItemPDF, itemLink, serverKey);
		if success then
			if getmetatable(result) == bellCurveMeta then
				print(engineLib.GetName() .. L[": Mean = "] .. result.mean .. L[", Standard Deviation = "] .. result.stddev);
			else
				print(engineLib.GetName() .. L[": Non-Standard PDF: "] .. tostring(result));
			end
		else
			print(engineLib.GetName() .. L[": Reported error: "] .. tostring(result));
		end
	end
end

--[[===========================================================================
--|| Deprecation Alert Functions
--||=========================================================================]]
do
    local SOURCE_PATTERN = "([^\\/:]+:%d+): in function `([^\"']+)[\"']";
    local seenCalls = {};
    local uid = 0;

    -------------------------------------------------------------------------------
    -- Shows a deprecation alert. Indicates that a deprecated function has
    -- been called and provides a stack trace that can be used to help
    -- find the culprit.
    -- @param replacementName (Optional) The displayable name of the replacement function
    -- @param comments (Optional) Any extra text to display
    -------------------------------------------------------------------------------
    function lib.ShowDeprecationAlert(replacementName, comments)
        local caller, source, functionName =
            debugstack(3):match(SOURCE_PATTERN),        -- Keep in mind this will be truncated to only the first in the tuple
            debugstack(2):match(SOURCE_PATTERN);        -- This will give us both the source and the function name

        functionName = functionName .. "()";

        -- Check for this source & caller combination
        seenCalls[source] = seenCalls[source] or {};
        if not seenCalls[source][caller] then
            -- Not warned yet, so warn them!
            seenCalls[source][caller]=true
            -- Display it
            AucAdvanced.Print(
                L["Auctioneer Advanced: "]..
                functionName .. L[" has been deprecated and was called by |cFF9999FF"]..caller:match("^(.+)%.[lLxX][uUmM][aAlL]:").."|r. "..
                (replacementName and (L["Please use "]..replacementName..L[" instead. "]) or "")..
                (comments or "")
            );
	        geterrorhandler()(
	            "Deprecated function call occurred in AuctioneerAdvanced API:\n     {{{Deprecated Function:}}} "..functionName..
	                "\n     {{{Source Module:}}} "..source:match("^(.+)%.[lLxX][uUmM][aAlL]:")..
	                "\n     {{{Calling Module:}}} "..caller:match("^(.+)%.[lLxX][uUmM][aAlL]:")..
	                "\n     {{{Available Replacement:}}} "..replacementName..
	                (comments and "\n\n"..comments or "")
			)
		end



    end

end

--Strong,在物品提示处增加卷轴成本，参考EnxTooltip.lua，EnxUtil.lua
--考虑将这些东西存储下来直接写入插件
local function createReagentList(...)
	local n = select("#", ... )
	local reagentList = {}
	for i = 1, n do
		local oneEntry = select(i, ...)
		local itemNumber, itemCount = strsplit(":", oneEntry);
		itemNumber = tonumber(itemNumber)
		itemCount = tonumber(itemCount)
		reagentList[i] = { itemNumber, itemCount }
	end
	return reagentList
end

local function dissectReagentEntryString(entryString)
	if not entryString then
		return
	end
	assert(type(entryString) == "string")
	local reagentList = createReagentList( strsplit(";", entryString ) );
	return reagentList
end

local function agetReagentsFromTradeFrame(craftIndex)
	local reagentList = {}

	local numReagents = GetTradeSkillNumReagents(craftIndex)
	for i = 1, numReagents do
		local link = GetTradeSkillReagentItemLink(craftIndex, i)
		if link then
			local hlink = link:match("|H([^|]+)|h")
			local reagentName, reagentTexture, reagentCount, playerReagentCount = GetTradeSkillReagentInfo(craftIndex, i)
			table.insert(reagentList, {hlink, reagentCount})
		end
	end

	return reagentList
end

function getReagentsFromCache(name)
	local reagentList = {}
  local ReagentCache = {
			["附魔盾牌 - 初级耐力"] = "10998:1;10940:2",
			["附魔护腕 - 特效智力"] = "22447:3",
			["附魔靴子 - 初级敏捷"] = "10940:6;10998:2",
			["附魔披风 - 防御"] = "11138:1;11083:3",
			["附魔护腕 - 耐力"] = "11083:6",
			["附魔胸甲 - 优异属性"] = "22449:4;22445:4;22446:4",
			["附魔护腕 - 力量"] = "11137:1",
			["附魔胸甲 - 状态"] = "11178:1;11176:3;11175:2",
			["附魔武器 - 超强打击"] = "14344:2;16203:4",
			["附魔长靴 - 稳固"] = "22450:2;22449:4",
			["附魔长靴 - 豹之迅捷"] = "22449:8;22451:8",
			["附魔护腕 - 强效智力"] = "16202:3",
			["附魔手套 - 草药学"] = "11083:1;3356:3",
			["附魔手套 - 力量"] = "11174:2;11137:3",
			["附魔手套 - 突袭"] = "22445:8",
			["附魔护腕 - 法力回复"] = "16204:4;16202:4;7080:2",
			["附魔胸甲 - 强效生命"] = "11083:3",
			["附魔护腕 - 属性"] = "22445:6;22447:6",
			["附魔胸甲 - 特效生命"] = "14343:2",
			["附魔手套 - 精确打击"] = "22446:8;22445:2;22449:2",
			["附魔护腕 - 优秀法力回复"] = "22446:8",
			["附魔披风 - 次级敏捷"] = "11174:2",
			["附魔披风 - 强效敏捷"] = "22446:1;22445:4;22451:1",
			["附魔护腕 - 突袭"] = "22445:6",
			["附魔双手武器 - 次级智力"] = "10939:3",
			["附魔盾牌 - 强效耐力"] = "11176:5",
			["附魔披风 - 潜行"] = "22448:3;22446:3;22794:2",
			["附魔胸甲 - 初级生命"] = "10940:1",
			["附魔双手武器 - 强效冲击"] = "11178:2;11176:2",
			["附魔护腕 - 强壮"] = "22445:6",
			["附魔武器 - 强效攻击"] = "11178:2;11175:2",
			["附魔披风 - 次级防护"] = "10940:6;10978:1",
			["附魔靴子 - 敏捷"] = "11175:2",
			["附魔护腕 - 强效力量"] = "11176:2;11175:1",
			["附魔戒指 - 法术能量"] = "22449:2;22446:2",
			["附魔胸甲 - 特效韧性"] = "22446:4;22445:10",
			["附魔手套 - 特效治疗"] = "22446:6;22449:6;21886:6",
			["附魔武器 - 猫鼬"] = "22450:6;22449:10;22446:8;22445:40",
			["附魔武器 - 攻击"] = "11135:2;11139:1",
			["附魔护腕 - 次级精神"] = "10998:2",
			["附魔盾牌 - 抗性"] = "22449:2;22573:1;22574:1;22572:1;22578:1",
			["附魔双手武器 - 初级冲击"] = "10940:4;10978:1",
			["附魔胸甲 - 次级生命"] = "10940:2;10938:2",
			["附魔武器 - 次级元素杀手"] = "11134:1;7067:1;11138:1",
			["附魔护腕 - 初级耐力"] = "10940:3",
			["附魔武器 - 冰寒"] = "14343:4;7080:1;7082:1;13467:1",
			["附魔胸甲 - 优秀法力回复"] = "22447:2;22445:2",
			["附魔披风 - 强效暗影抗性"] = "22449:4;22456:8",
			["附魔手套 - 冲击"] = "22447:1;22445:4",
			["附魔双手武器 - 超强冲击"] = "14344:4;16204:10",
			["附魔武器 - 次级屠兽"] = "11134:1;5637:2;11138:1",
			["附魔披风 - 次级火焰抗性"] = "6371:1;10998:1",
			["附魔盾牌 - 特效耐力"] = "22445:15",
			["附魔靴子 - 精神"] = "16203:2",
			["附魔手套 - 特效力量"] = "22445:12;22446:1",
			["附魔戒指 - 治疗能量"] = "22449:2;22446:3;22445:5",
			["附魔靴子 - 次级精神"] = "11135:1;11134:2",
			["附魔披风 - 初级防护"] = "10940:3;10939:1",
			["附魔武器 - 烈焰"] = "11177:4;7078:1",
			["附魔武器 - 潜能"] = "22449:4;22446:5;22445:20",
			["附魔胸甲 - 初级属性"] = "11082:1;11083:1;11084:1",
			["附魔手套 - 剥皮"] = "11137:1",
			["附魔盾牌 - 活力"] = "16203:1;16204:4",
			["附魔武器 - 特效智力"] = "22449:2;22446:10",
			["附魔披风 - 超强防御"] = "16204:8",
			["附魔胸甲 - 初级法力"] = "10938:1",
			["附魔手套 - 高级采矿"] = "11137:3;6037:3",
			["附魔披风 - 初级敏捷"] = "10998:1",
			["附魔披风 - 钢纹"] = "22446:8;22452:8",
			["附魔盾牌 - 耐力"] = "11137:5",
			["附魔靴子 - 强效耐力"] = "11176:5",
			["附魔护腕 - 超强精神"] = "16202:3;11176:4",
			["附魔武器 - 初级攻击"] = "10940:2;10939:1;10978:1",
			["附魔护腕 - 初级精神"] = "10938:2",
			["附魔护腕 - 次级耐力"] = "11083:2",
			["附魔胸甲 - 法力"] = "11082:1;10998:2",
			["附魔武器 - 初级屠兽"] = "10940:4;10939:2",
			["附魔长靴 - 活力"] = "22445:6;13446:4;13444:4",
			["附魔靴子 - 初级速度"] = "11177:1;7909:1;11174:1",
			["附魔胸甲 - 防御"] = "22446:4;22445:8;23427:4",
			["附魔双手武器 - 野蛮"] = "22449:4;22445:40",
			["附魔手套 - 强效敏捷"] = "16202:2;16204:3",
			["附魔长靴 - 坚韧"] = "22445:12",
			["附魔盾牌 - 智力"] = "22446:4",
			["附魔护腕 - 次级智力"] = "11082:2",
			["附魔胸甲 - 次级吸收"] = "10940:2;11082:1;11084:1",
			["附魔武器 - 寒冬之力"] = "11135:3;11137:3;11139:1;3819:2",
			["附魔武器 - 次级攻击"] = "11083:2;11084:1",
			["附魔手套 - 强效力量"] = "16202:4;16204:4",
			["附魔手套 - 初级加速"] = "11178:2;8153:2",
			["附魔盾牌 - 次级精神"] = "10998:2;10940:4",
			["附魔护腕 - 超强耐力"] = "16204:10",
			["附魔披风 - 初级抗性"] = "10940:1;10938:2",
			["附魔披风 - 强效火焰抗性"] = "22448:3;22446:3;7078:4",
			["附魔武器 - 阳炎"] = "22450:12;22449:10;22446:8;21884:6;23571:1",
			["附魔长靴 - 灵巧"] = "22446:8;22445:8",
			["附魔武器 - 特效法术能量"] = "22449:8;22446:8",
			["附魔盾牌 - 韧性"] = "22449:1;22447:4",
			["附魔胸甲 - 生命"] = "10940:4;10998:1",
			["附魔胸甲 - 特效法力"] = "16204:8",
			["附魔胸甲 - 超强生命"] = "11137:6",
			["附魔披风 - 强效抗性"] = "7077:1;7075:1;7079:1;7081:1;7972:1",
			["附魔护腕 - 特效防御"] = "22448:2;22445:10",
			["附魔手套 - 超强敏捷"] = "22448:3;22446:3;22451:2",
			["附魔武器 - 邪恶武器"] = "14344:4;12808:4",
			["附魔手套 - 特效法术能量"] = "22446:6;22449:6;22457:6",
			["附魔靴子 - 强效敏捷"] = "16202:2;8153:2",
			["附魔双手武器 - 特效精神"] = "16203:4;14344:2",
			["附魔双手武器 - 次级精神"] = "10998:1;10940:6",
			["附魔胸甲 - 强效法力"] = "11135:1",
			["附魔护腕 - 偏斜"] = "11175:1;11176:2",
			["附魔披风 - 强效防御"] = "11137:3",
			["附魔靴子 - 次级敏捷"] = "11083:1;11134:1",
			["附魔胸甲 - 优异生命"] = "22445:8;13446:4;14344:2",
			["附魔胸甲 - 特效精神"] = "22446:2",
			["附魔护腕 - 精神"] = "11134:1",
			["附魔护腕 - 强效精神"] = "11174:3;11137:1",
			["附魔武器 - 生命偷取"] = "14344:4;12808:4;12803:4",
			["附魔武器 - 魂霜"] = "22450:12;22449:10;22446:8;21885:6;22456:6",
			["附魔武器 - 屠魔"] = "11177:1;11176:2;9224:1",
			["附魔护腕 - 超强治疗"] = "22446:4;21886:4",
			["附魔武器 - 特效治疗"] = "22449:8;21885:8;21886:8",
			["附魔披风 - 强效自然抗性"] = "22448:2;22446:3;12803:4",
			["附魔武器 - 斩杀"] = "22450:6;22449:10;22446:6;22445:30;22824:3",
			["附魔披风 - 火焰抗性"] = "11134:1;7068:1",
			["附魔靴子 - 次级耐力"] = "11083:4",
			["附魔胸甲 - 初级吸收"] = "10940:2;10938:1",
			["附魔手套 - 敏捷"] = "11174:1;11137:1",
			["附魔盾牌 - 次级防护"] = "10998:1;10940:1;10978:1",
			["附魔护腕 - 初级敏捷"] = "10940:2;10939:1",
			["附魔胸甲 - 超强法力"] = "11175:1;11174:2",
			["附魔披风 - 法术穿透"] = "22446:2;22445:6;22457:2",
			["附魔胸甲 - 次级状态"] = "11135:2;11137:2;11139:1",
			["附魔护腕 - 智力"] = "11174:2",
			["附魔双手武器 - 冲击"] = "11137:4;11139:1",
			["附魔护腕 - 次级偏斜"] = "11134:1;11083:2",
			["附魔披风 - 抗性"] = "11174:1",
			["附魔双手武器 - 敏捷"] = "14344:8;7082:4",
			["附魔盾牌 - 强效精神"] = "11175:1;11176:2",
			["附魔护腕 - 初级生命"] = "10940:1",
			["附魔护腕 - 强效耐力"] = "11176:5",
			["附魔护腕 - 初级偏斜"] = "10938:1;10940:1",
			["附魔护腕 - 坚韧"] = "22449:1;22446:10;22445:20",
			["附魔武器 - 十字军"] = "14344:4;12811:2",
			["附魔武器 - 强效敏捷"] = "22445:8;22446:4;22449:6;22451:2",
			["附魔双手武器 - 次级冲击"] = "11083:3;11084:1",
			["附魔盾牌 - 精神"] = "11135:1;11137:1",
			["附魔护腕 - 次级力量"] = "11083:2",
			["附魔戒指 - 属性"] = "22450:2;22449:2",
			["附魔盾牌 - 次级耐力"] = "11134:1;11083:1",
			["附魔双手武器 - 特效智力"] = "16203:4;14344:2",
			["附魔护腕 - 法术能量"] = "22449:6;21884:6;21885:6",
			["附魔手套 - 钓鱼"] = "11083:1;6370:3",
			["附魔武器 - 作战专家"] = "22450:8;22449:8;21885:2",
			["附魔靴子 - 耐力"] = "11137:5",
			["附魔披风 - 特效护甲"] = "22445:8",
			["附魔披风 - 次级暗影抵抗"] = "11082:1;6048:1",
			["附魔护腕 - 治疗能力"] = "14344:2;16204:4;16202:4",
			["附魔盾牌 - 坚韧盾牌"] = "22445:6;22452:10",
			["附魔靴子 - 初级耐力"] = "10940:8",
			["附魔护腕 - 初级力量"] = "10940:5",
			["附魔胸甲 - 次级法力"] = "10939:1;10938:1",
			["附魔双手武器 - 特效敏捷"] = "22449:8;22446:6;22445:20",
		}
		
	local entryString = ReagentCache [ name ];
	if (not entryString) then
		return nil;
	end
	local reagentList = dissectReagentEntryString(entryString);
	return reagentList		
end

---Strong,卷轴成本提示，查找技能名。目前必须打开附魔技能
function getCPrice(name)
	if ( name:find("卷轴：") == nil ) then 
		return nil
	end
	
	name = name:gsub("卷轴：", "")
	
	--修正潜能
	local t0,t1
	t0,_ = name:find("武器")
	t1,_ = name:find("力量")
	if (t0 and t1 ) then
		name = name:gsub(	"力量","潜能")
	end

	--name = name:gsub("附魔武器　-　力量", "附魔武器　-　潜能")	-- 

	local reagentList
	reagentList = getReagentsFromCache(name)
	if ( not reagentList ) then  -- 试图从技能中直接得到，得到后应该保存
			local tradeIndex = nil
			for i = GetFirstTradeSkill(), GetNumTradeSkills() do
				local tradeName = GetTradeSkillInfo(i);
				if name == tradeName then
					tradeIndex = i
					break
				end
			end
	
		if ( not tradeIndex ) then 
			return nil
		end
		reagentList = agetReagentsFromTradeFrame(tradeIndex)
	end
	
	if not reagentList or (#reagentList < 1) then
			--Enchantrix.Util.DebugPrintQuick("no reagents found for ", link, " in ", name )
		return nil
	end
	for _, reagent in ipairs(reagentList) do
		local rName, _, rQuality = GetItemInfo(reagent[1])
		local style, extra = "average",nil
		local hsp, median, market, five, fix 
		local reagentID = reagent[1]
		if type(reagentID) == "string" then
			local _, _, i = reagentID:find("item:(%d+):")
			reagentID = i
	  end
	  reagentID = tonumber(reagentID)
		local _, link = GetItemInfo(reagentID);
		five = AucAdvanced.API.GetMarketValue(link);
		----= Enchantrix.Util.GetReagentPrice(reagent[1],extra)
		if Auctioneer 
			and Auctioneer.Util and Auctioneer.Statistic then
			local itemKey = ("%d:0:0"):format(reagentID);
			local realm = Auctioneer.Util.GetAuctionKey()
			hsp = Auctioneer.Statistic.GetHSP(itemKey, realm)
			median = Auctioneer.Statistic.GetUsableMedian(itemKey, realm)
		end
    
		local _, _, _, color = GetItemQualityColor(rQuality)

		reagent[1] = rName
		table.insert(reagent, rQuality)
		table.insert(reagent, color)
		table.insert(reagent, five)

	end	
	
	local aNAME, aCOUNT, aQUALITY, aCOLOR, aPRICE = 1, 2, 3, 4, 5

	-- Sort by rarity and price
	table.sort(reagentList, function(a,b)
		if (not b) or (not a) then return end
		return ((b[aQUALITY] or -1) < (a[aQUALITY] or -1)) or ((b[aPRICE] or 0) < (a[aPRICE] or 0))
	end)

	-- Header
	local price = 0
	local unknownPrices
	-- Add reagent list to tooltip and sum reagent prices
	for _, reagent in pairs(reagentList) do

		if reagent[aCOUNT] > 1 and reagent[aPRICE] then
			price = price + reagent[aPRICE] * reagent[aCOUNT]
		elseif reagent[aPRICE] then
			price = price + reagent[aPRICE]
		else
			unknownPrices = true
		end
	end

	if price > 0 then
		price = (price + 200000)*1.15
		return price
	end
	return nil
end

function lib.CancelNonMBOs(pattern, undercutLimit)
   local aucNumOwn = GetNumAuctionItems("owner")
   local playerName = UnitName("player")
   for i=1,aucNumOwn do    
      local tmp       
      local itemName, tmp, tmp, tmp, tmp, tmp, tmp, tmp, boOwn = GetAuctionItemInfo("owner",i)       
       if itemName:find(pattern) then                   
         local linkType,itemId,property,factor = AucAdvanced.DecodeLink(GetAuctionItemLink("owner",i))    
         if (linkType ~= "item") then return end          
         itemId = tonumber(itemId)       
         property = tonumber(property) or 0       
         factor = tonumber(factor) or 0       
         local data = AucAdvanced.API.QueryImage({       
         itemId = itemId,       
         suffix = property,       
         factor = factor,       
         })                 
          competing = #data   
         local cbuy 
         cbuy = getCPrice(itemName)
         if not cbuy then 

         		cbuy = 0 
         end
         --DEFAULT_CHAT_FRAME:AddMessage("-----"..itemName.."-----")
         
         for j = 1, #data do    
            local compet = AucAdvanced.API.UnpackImageItem(data[j])
            compet.buyoutPrice = (compet.buyoutPrice/compet.stackSize)
            if compet.sellerName ~= playerName then       
               if compet.buyoutPrice < boOwn and boOwn > (cbuy+10000) and compet.buyoutPrice >= undercutLimit then
                  CancelAuction(i)          
                  local mess = itemName .. " canceled. Current MBO: " .. compet.sellerName .. " - " .. compet.buyoutPrice    
                  DEFAULT_CHAT_FRAME:AddMessage(mess,1.0,0.0,0.0)            
                   break          
               end          
            end             
         end          
      end       
   end    
end


AucAdvanced.RegisterRevision("$URL: http://svn.norganna.org/auctioneer/branches/5.6/Auc-Advanced/CoreAPI.lua $", "$Rev: 4279 $")
